<template>
  <div>
    <el-button link type="primary" @click="handleClick">围栏设置</el-button>
    <teleport to="body">
      <el-dialog v-model="showDialog" destroy-on-close :title="title" width="80%" @close="handleClose">
        <search-component :has-fence="hasActiveFence" @clear-fence-triggered="clearFence" @update-center="handleSearchCenterUpdate" />
        <div id="mainMapContainer">
          <div ref="mapContainer" class="map-container">
            <!-- <el-button type="primary" @click="clearFence">清除围栏</el-button> Removed old button -->

            <div id="container" style="width: 100%; height: 100%"></div>
            <!-- 地图右键菜单 -->
            <div id="contextmenu_map" class="contextmenu_map">
              <div class="contextmenu_map_item" @click="addMarker(true)">添加坐标点</div>
            </div>
            <!-- Marker右键菜单 -->
            <div id="contextmenu_marker" class="contextmenu_marker">
              <div class="contextmenu_marker_item" @click="delMarkerFn">删除</div>
            </div>
          </div>
        </div>
        <template #footer>
          <span class="dialog-footer">
            <el-button @click="handleClose">取消</el-button>
            <el-button type="primary" @click="handleSave">确定</el-button>
          </span>
        </template>
      </el-dialog>
    </teleport>
  </div>
</template>

<script setup lang="ts">
import { useScriptTag } from '@vueuse/core'
import { ElMessage } from 'element-plus'
import { nextTick, onUnmounted, ref, watch } from 'vue'
import type { MapEvent } from '~/src/types/map'
import SearchComponent from './components/SearchComponent.vue'

interface Props {
  initialPoints?: string[] // 初始围栏点
}

const props = defineProps<Props>()
const showMap = ref(false)
const emits = defineEmits<{
  (e: 'save', points: string[]): void // 保存围栏点
}>()

// 定义与 SearchComponent 交互的坐标类型
interface CenterCoordinates {
  lat: number
  lng: number
}

declare const T: any

// 新增：用于存储搜索结果的临时标记
const searchMarker = ref<any>(null)
const hasActiveFence = ref(false) // New reactive state for fence existence

interface FenceAssembly {
  TMapMarker: any[]
  latlngArr: string[]
  latlngStr: string
  polygon: any
  points?: any[]
}

const showDialog = ref(false)

const title = ref('围栏设置')
const TMap = ref<any>(null)
const mapInitialized = ref(false)
const primaryColor = ref('#0249f9')
const addMarkerPos = ref<any>(null)
const delMarkerIndex = ref(-1)
const fenceAssembly = ref<FenceAssembly>({
  TMapMarker: [],
  latlngArr: [],
  latlngStr: '',
  polygon: null,
})

// 使用 useScriptTag 加载天地图 API
const scriptStatus = ref(false)
const { load } = useScriptTag(
  'https://api.tianditu.gov.cn/api?v=4.0&tk=4c23f5e81bf0497296f2ff0e0bcb43c2',
  () => {
    scriptStatus.value = true
  },
  {
    manual: true,
    async: false,
    defer: true,
  }
)

const debugLog = (message: string, data?: any) => {
  console.log(`[Map组件] ${message}`, data || '')
}

const mapContainer = ref<HTMLElement | null>(null)

const mapKey = ref(0) // 用于强制重新渲染地图组件

// 延迟函数
// const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))

// 初始化地图
async function initTMap() {
  try {
    if (!mapContainer.value) {
      throw new Error('地图容器 DOM 元素未找到或未渲染')
    }
    debugLog('找到地图容器')

    const center = new T.LngLat(84.885205, 45.575793)
    TMap.value = new T.Map('container')

    if (TMap.value) {
      debugLog('地图实例创建成功')
      TMap.value.centerAndZoom(center, 15)
      setupEditMode()
      mapInitialized.value = true

      // 如果有初始数据，绘制围栏
      if (fenceAssembly.value.latlngArr.length > 0) {
        debugLog('使用初始数据绘制围栏', fenceAssembly.value.latlngArr)
        await nextTick()
        operateTMap()
      }
    }
  } catch (error) {
    console.error('地图初始化失败:', error)
    throw error
  }
}

// // 加载地图
// async function loadMap() {
//   try {
//     debugLog('开始加载地图')
//     if (!scriptStatus.value) {
//       await load()
//       // 等待脚本加载完成
//       await new Promise<void>((resolve) => {
//         const checkScript = () => {
//           if (scriptStatus.value && T !== undefined) {
//             resolve()
//           } else {
//             setTimeout(checkScript, 100)
//           }
//         }
//         checkScript()
//       })
//       debugLog('地图脚本加载完成')
//     }

//     await nextTick()
//     await initTMap()
//   } catch (error) {
//     console.error('地图加载失败:', error)
//     ElMessage.error('地图加载失败，请刷新页面重试')
//   }
// }

// 点击按钮时打开对话框并加载地图
async function handleClick() {
  debugLog('点击打开地图', { initialPoints: props.initialPoints })
  showDialog.value = true
  mapKey.value++ // 每次打开都强制重新渲染
  // 设置初始数据
  fenceAssembly.value.latlngArr = props.initialPoints || []
  hasActiveFence.value = !!(props.initialPoints && props.initialPoints.length > 0) // Initialize hasActiveFence
}

function setupEditMode() {
  if (!TMap.value) return

  const checkAndAddMarker = (event: MapEvent, immediateAdd = false) => {
    if (fenceAssembly.value.latlngArr.length >= 20) {
      ElMessage({
        message: '电子围栏最多允许添加20个坐标点！',
        type: 'warning',
      })
      return
    }
    addMarkerPos.value = new T.LngLat(event.lnglat.lng, event.lnglat.lat)
    if (immediateAdd) {
      addMarker(true)
      contextmenuFn('')
    } else {
      contextmenuFn('map', event.containerPoint.x, event.containerPoint.y)
    }
  }

  TMap.value.addEventListener('click', (event: MapEvent) => {
    checkAndAddMarker(event, true)
  })

  TMap.value.addEventListener('contextmenu', (event: MapEvent) => {
    checkAndAddMarker(event)
  })
}

function operateTMap() {
  if (!TMap.value) {
    debugLog('地图未初始化，无法操作')
    return
  }

  debugLog('开始操作地图', { points: fenceAssembly.value.latlngArr })
  TMap.value.clearOverLays()
  const data = fenceAssembly.value.latlngArr

  // 清理现有标记点的事件
  fenceAssembly.value.TMapMarker.forEach((marker) => {
    marker.removeEventListener('dragend')
    marker.removeEventListener('contextmenu')
  })
  fenceAssembly.value.TMapMarker = []

  // 添加标记点
  data.forEach((ele, index) => {
    debugLog(`添加第 ${index + 1} 个标记点`, ele)
    const [lat, lng] = ele.split(',').map(Number)
    if (!isNaN(lat) && !isNaN(lng)) {
      addMarkerPos.value = new T.LngLat(lng, lat)
      addMarker()
    }
  })

  // 操作地图前清除搜索标记（如果存在）
  if (searchMarker.value) {
    TMap.value.removeOverLay(searchMarker.value)
    searchMarker.value = null
  }

  // 绘制多边形
  const points = data.map((ele) => {
    const [lat, lng] = ele.split(',').map(Number)
    return new T.LngLat(lng, lat)
  })

  if (points.length >= 3) {
    debugLog('绘制围栏多边形', points)
    fenceAssembly.value.points = points
    fenceAssembly.value.polygon = new T.Polygon(points, {
      color: primaryColor.value,
      weight: 3,
      opacity: 1,
      fillColor: primaryColor.value,
      fillOpacity: 0.2,
    })
    TMap.value.addOverLay(fenceAssembly.value.polygon)
    hasActiveFence.value = true // Set when polygon is drawn

    // Adjust map viewport to fit the polygon
    if (fenceAssembly.value.polygon && points && points.length > 0) {
      try {
        TMap.value.setViewport(points) // Automatically adjust zoom and center
        debugLog('地图视野已根据围栏调整')
      } catch (error) {
        debugLog('调整地图视野时出错:', error)
        // Fallback to panTo center if setViewport fails for some reason
        try {
          const bounds = fenceAssembly.value.polygon.getBounds()
          if (bounds) {
            const center = bounds.getCenter()
            if (center) {
              TMap.value.panTo(center)
            }
          }
        } catch (centerError) {
          debugLog('备用聚焦中心点也失败:', centerError)
        }
      }
    }
  } else {
    fenceAssembly.value.polygon = null
    hasActiveFence.value = false // Set if not enough points for a polygon
  }
}

function addMarker(isManualAdd = false) {
  if (!TMap.value || !addMarkerPos.value) return

  // 添加围栏点时清除搜索标记
  if (searchMarker.value) {
    TMap.value.removeOverLay(searchMarker.value)
    searchMarker.value = null
  }

  const markerIndex = fenceAssembly.value.TMapMarker.length

  generateTextImage(markerIndex + 1, (url: string) => {
    const icon = new T.Icon({
      iconUrl: url,
      iconAnchor: new T.Point(10, 10),
    })

    const marker = new T.Marker(addMarkerPos.value, { icon })
    fenceAssembly.value.TMapMarker.push(marker)

    TMap.value.addOverLay(marker)
    marker.enableDragging()

    marker.addEventListener('dragend', (event: MapEvent) => {
      const { lat, lng } = event.lnglat
      const latlngStr = `${lat},${lng}`
      fenceAssembly.value.latlngArr[markerIndex] = latlngStr
      fenceAssembly.value.latlngStr = fenceAssembly.value.latlngArr.join(';')
      operateTMap()
    })

    marker.addEventListener('contextmenu', (event: MapEvent) => {
      delMarkerIndex.value = markerIndex
      contextmenuFn('marker', event.containerPoint.x, event.containerPoint.y)
    })

    if (isManualAdd && addMarkerPos.value) {
      const { lat, lng } = addMarkerPos.value
      const latlngStr = `${lat},${lng}`
      fenceAssembly.value.latlngArr.push(latlngStr)
      fenceAssembly.value.latlngStr = fenceAssembly.value.latlngArr.join(';')
      contextmenuFn('')
      operateTMap()
    }
  })
}

function delMarkerFn() {
  fenceAssembly.value.latlngArr.splice(delMarkerIndex.value, 1)
  fenceAssembly.value.latlngStr = fenceAssembly.value.latlngArr.join(';')
  contextmenuFn('')
  operateTMap()
}

function generateTextImage(text: number, callback: (url: string) => void) {
  const canvas = document.createElement('canvas')
  const ctx = canvas.getContext('2d')
  if (!ctx) return

  canvas.width = 20
  canvas.height = 20
  ctx.beginPath()
  ctx.arc(10, 10, 10, 0, 2 * Math.PI)
  ctx.fillStyle = primaryColor.value
  ctx.fill()
  ctx.fillStyle = '#ffffff'
  ctx.font = '15px Arial'
  ctx.textAlign = 'center'
  ctx.textBaseline = 'middle'
  ctx.fillText(text.toString(), canvas.width / 2, canvas.height / 1.8)
  const dataURL = canvas.toDataURL('image/png')
  callback(dataURL)
}

function contextmenuFn(mode = '', left?: number, top?: number) {
  const elements = {
    map: document.getElementById('contextmenu_map'),
    marker: document.getElementById('contextmenu_marker'),
  }

  if (mode && left != null && top != null) {
    const element = elements[mode as keyof typeof elements]
    if (element) {
      element.style.display = 'block'
      element.style.left = `${left}px`
      element.style.top = `${top}px`
    }
  }

  Object.entries(elements).forEach(([key, element]) => {
    if (key !== mode && element) {
      element.style.display = 'none'
    }
  })
}

function clearFence() {
  fenceAssembly.value.latlngArr = []
  fenceAssembly.value.latlngStr = ''
  fenceAssembly.value.TMapMarker = []
  fenceAssembly.value.polygon = null
  if (TMap.value) TMap.value.clearOverLays()

  // 清除搜索时添加的临时标记
  if (searchMarker.value && TMap.value) {
    TMap.value.removeOverLay(searchMarker.value)
    searchMarker.value = null
  }
  hasActiveFence.value = false // Update active fence state
}

function handleClose() {
  showDialog.value = false
}

const handleSave = async () => {
  if (fenceAssembly.value.latlngArr.length > 0) {
    await new Promise((resolve) => setTimeout(resolve, 300))
    emits('save', fenceAssembly.value.latlngArr)
  } else {
    ElMessage.warning('请先设置围栏点')
  }
}

// 监听弹窗状态
watch(
  () => showDialog.value,
  async (newVal) => {
    debugLog('弹窗状态变化', { isOpen: newVal })
    if (newVal) {
      showMap.value = true
      await nextTick()
      await ensureMapReady()
    } else {
      destroyMap()
      showMap.value = false
    }
  }
)

// 监听初始点位变化
watch(
  () => props.initialPoints,
  (newPoints) => {
    debugLog('初始点位变化', newPoints)
    if (newPoints && newPoints.length > 0) {
      fenceAssembly.value.latlngArr = newPoints
      // 如果地图已经初始化且弹窗打开，则重新绘制围栏
      if (mapInitialized.value && showDialog.value) {
        debugLog('重新绘制围栏')
        operateTMap()
      }
    }
  }
)

// 组件卸载时清理资源
onUnmounted(() => {
  destroyMap()
})

// 新增：处理 SearchComponent 的 update-center 事件
const handleSearchCenterUpdate = (center: CenterCoordinates) => {
  if (TMap.value && center) {
    debugLog('SearchComponent 请求更新地图中心点', center)
    const newCenter = new T.LngLat(center.lng, center.lat)

    // 清除上一个搜索标记
    if (searchMarker.value) {
      TMap.value.removeOverLay(searchMarker.value)
      searchMarker.value = null
    }

    // 创建新的搜索标记 (可以使用不同的图标)
    // 例如，使用默认图标
    searchMarker.value = new T.Marker(newCenter)
    TMap.value.addOverLay(searchMarker.value)

    TMap.value.panTo(newCenter)
    // TMap.value.setZoom(15) // 您可以根据需要设置缩放级别
  } else {
    debugLog('地图未就绪或中心点数据缺失，无法更新地图中心')
  }
}

// 新增：确保地图准备就绪的函数
async function ensureMapReady() {
  if (mapInitialized.value) {
    debugLog('地图已初始化，跳过')
    return
  }
  try {
    if (scriptStatus.value) {
      debugLog('脚本已加载')
    } else {
      debugLog('脚本未加载，开始加载...')
      await load() // 尝试加载脚本
      // 等待脚本加载完成或 T 对象可用
      await new Promise<void>((resolve, reject) => {
        let attempt = 0 // 添加简单超时计数
        const maxAttempts = 100 // 例如 10 秒超时 (100 * 100ms)

        const checkScript = () => {
          // 主要检查全局 T 对象是否存在
          if (T !== undefined) {
            debugLog('地图脚本 T 对象已可用')
            scriptStatus.value = true // 确保状态一致性
            resolve()
          } else if (attempt >= maxAttempts) {
            reject(new Error(`地图脚本加载超时 (${maxAttempts * 100}ms)，T 对象未定义`))
          } else {
            attempt++
            setTimeout(checkScript, 100) // 每 100ms 检查一次
          }
        }
        checkScript() // 开始检查
      })
    }

    await initTMap() // 脚本就绪后初始化地图
  } catch (error) {
    console.error('地图准备失败:', error)
    ElMessage.error(`地图准备失败: ${error instanceof Error ? error.message : '未知错误'}`)
  }
}

// 新增：销毁地图实例的函数
function destroyMap() {
  if (TMap.value) {
    debugLog('开始清理地图状态（依赖 destroy-on-close）')

    // 可以在这里调用天地图库提供的任何纯粹的清理方法（如果存在）
    // 例如，移除全局事件监听器等，但不要操作特定的 DOM 元素
    // TMap.value.clearOverLays(); // 如果需要的话

    // 1. Reset Vue state
    TMap.value = null
    mapInitialized.value = false
    fenceAssembly.value = {
      TMapMarker: [],
      latlngArr: [],
      latlngStr: '',
      polygon: null,
    }
    addMarkerPos.value = null
    delMarkerIndex.value = -1

    // 清理搜索标记
    if (searchMarker.value) {
      // 注意：由于 destroy-on-close，地图实例理论上已销毁，
      // 直接操作 TMap.value 可能不安全或无效。
      // searchMarker 本身在组件销毁时会被重置为 null，所以这里主要是状态重置。
      searchMarker.value = null
    }

    debugLog('地图 Vue 状态已清理')
  } else {
    debugLog('没有地图实例需要销毁/清理')
  }
}
</script>

<style scoped>
.map-container {
  position: relative;
  width: 100%;
  height: 450px;
}

.map-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 450px;
  background-color: #f5f7fa;
}

#mainMapContainer {
  position: relative;
  width: 100%;
  height: 500px;
}

#container {
  width: 100%;
  height: 100%;
  background-color: #f1f1f1;
}

.contextmenu_map,
.contextmenu_marker {
  position: absolute;
  z-index: 1000;
  display: none;
  padding: 5px 0;
  background-color: #f9f9f9;
  border: 1px solid #ccc;
  border-radius: 4px;
  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
}

.contextmenu_map_item,
.contextmenu_marker_item {
  padding: 10px 20px;
  cursor: pointer;
}

.contextmenu_map_item:hover,
.contextmenu_marker_item:hover {
  background-color: #f1f1f1;
}

.dialog-footer {
  margin-top: 20px;
}
</style>
